﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Memcached.ClientLibrary;

namespace EWineShop.Cache
{
    /// <summary>
    /// MemcacheFactory缓存提供程序工厂
    /// </summary>
    public class MemcachedFactory : CacheProviderFactory
    {
        #region Fields

        /// <summary>
        /// 服务器列表
        /// </summary>
        private MemcachedServer[] servers;

        /// <summary>
        /// 进程锁
        /// </summary>
        private object syncRoot;
        
        /// <summary>
        /// memcache server pool name
        /// </summary>
        private string poolName;

        #endregion

        #region Constructors

        
        /// <summary>
        /// Memcache工厂
        /// </summary>
        /// <param name="servers">服务器列表</param>
        public MemcachedFactory(MemcachedServer[] servers)
        {
            if (servers == null)
            {
                throw new ArgumentNullException("servers", "服务器列表不能为空");
            }

            this.servers = servers;
            this.syncRoot = new object();
        }
        
        public MemcachedFactory(MemcachedServer[] servers,string poolName)
        {
        	if (servers == null)
            {
                throw new ArgumentNullException("servers", "服务器列表不能为空");
            }

            this.servers = servers;
            this.syncRoot = new object();
            this.poolName = poolName;
        }

        #endregion

        #region CacheProviderFactory Members

        /// <summary>
        /// 创建缓存提供器
        /// </summary>
        /// <returns>缓存提供器接口</returns>
        public override ICacheProvider CreateCacheProvider()
        {
        	MemcachedClient client = new MemcachedClient();
            SockIOPool sockIOPool = null;
            if(string.IsNullOrEmpty(this.poolName))
            	sockIOPool = SockIOPool.GetInstance();
            else
            {
            	sockIOPool = SockIOPool.GetInstance(this.poolName);
            	client.PoolName = this.poolName;
            }
            if (!sockIOPool.Initialized)
            {
                InitializeSockIOPool(sockIOPool);
            }

            return new MemcachedProvider(client);
        }
        
        /// <summary>
        /// 断开memcache连接
        /// </summary>
        public override void ClearUp()
        {
            SockIOPool sockIOPool = null;
            if(string.IsNullOrEmpty(this.poolName))
            	sockIOPool = SockIOPool.GetInstance();
            else
            	sockIOPool = SockIOPool.GetInstance(this.poolName);

            sockIOPool.Shutdown();
        }

        #endregion

        #region Helper Functions

        /// <summary>
        /// 初始化套接字输入输出缓冲池
        /// </summary>
        /// <param name="sockIOPool">套接字输入输出缓冲池</param>
        private void InitializeSockIOPool(SockIOPool sockIOPool)
        {
            lock (syncRoot)
            {
                if (!sockIOPool.Initialized)
                {
					//采用一致性hash算法
					sockIOPool.HashingAlgorithm = HashingAlgorithm.KetamaHash;

                    string[] serverStrings = new string[servers.Length];
                    int[] weights = new int[servers.Length];
                    for (int index = 0; index < servers.Length; ++index)
                    {
                        MemcachedServer server = servers[index];
                        serverStrings[index] = string.Format("{0}:{1}", server.Host, server.Port);
                        weights[index] = server.Weight;
                    }

                    sockIOPool.SetServers(serverStrings);
                    sockIOPool.SetWeights(weights);

                    sockIOPool.Initialize();

					
                }
            }
        }

        #endregion
    }
}
